library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use work.typeDefinitions.all;

entity idInterstageReg is
  port (
    clk            : in std_logic;
    nReset         : in std_logic;
    holdStage      : in std_logic;
    invalidate     : in std_logic;
    nPC_in         : in std_logic_vector(31 downto 0);
    immediate_in   : in std_logic_vector(31 downto 0);
    upper_in       : in std_logic_vector(31 downto 0);
    busA_in        : in std_logic_vector(31 downto 0);
    busB_in        : in std_logic_vector(31 downto 0);
    rs_in          : in std_logic_vector(4 downto 0);
    rt_in          : in std_logic_vector(4 downto 0);
    shftamnt_in    : in std_logic_vector(4 downto 0);
    destination_in : in std_logic_vector(4 downto 0);
    instruction_in : in operation;

    immediate   : out std_logic_vector(31 downto 0);
    upper       : out std_logic_vector(31 downto 0);
    busA        : out std_logic_vector(31 downto 0);
    busB        : out std_logic_vector(31 downto 0);
    shftamnt    : out std_logic_vector(4 downto 0);
    rs          : out std_logic_vector(4 downto 0);
    rt          : out std_logic_vector(4 downto 0);
    destination : out std_logic_vector(4 downto 0);
    instruction : out operation;
    nPC         : out std_logic_vector(31 downto 0));
end idInterstageReg;

architecture idInterstageReg_arch of idInterstageReg is

  signal r_instruction, n_instruction          : operation;
  signal r_busA, r_busB, n_busA, n_busB        : std_logic_vector(31 downto 0);
  signal r_nPC, n_nPC                          : std_logic_vector(31 downto 0);
  signal r_shftamnt, r_destination, r_rs, r_rt : std_logic_vector(4 downto 0);
  signal n_shftamnt, n_destination, n_rt, n_rs : std_logic_vector(4 downto 0);
  signal n_imm, r_imm, n_up, r_up              : std_logic_vector(31 downto 0);
  
begin  -- fetchInterstageReg  

  nPC         <= r_nPC;
  instruction <= r_instruction;
  destination <= r_destination;
  shftamnt    <= r_shftamnt;
  rt          <= r_rt;
  rs          <= r_rs;
  immediate   <= r_imm;
  busA        <= r_busA;
  busB        <= r_busB;
  upper       <= r_up;

  registers : process (clk, nReset, n_nPC, n_instruction, n_busA, n_busB, n_shftamnt, n_imm, n_destination)
  begin

    -- one register if statement
    if (nReset = '0') then
      -- Reset here
      
      r_instruction <= (o_nop);
      r_nPC         <= (others => '0');
      r_busA        <= (others => '0');
      r_busB        <= (others => '0');
      r_shftamnt    <= (others => '0');
      r_imm         <= (others => '0');
      r_up          <= (others => '0');
      r_rs          <= (others => '0');
      r_rt          <= (others => '0');
      r_destination <= (others => '0');
      
    elsif (falling_edge(clk)) then
      -- Set register here
      
      r_instruction <= n_instruction;
      r_nPC         <= n_nPC;
      r_busA        <= n_busA;
      r_busB        <= n_busB;
      r_shftamnt    <= n_shftamnt;
      r_imm         <= n_imm;
      r_up          <= n_up;
      r_destination <= n_destination;
      r_rt          <= n_rt;
      r_rs          <= n_rs;
      
    end if;
    
  end process;


  -- outputs: 
  nextState : process (holdStage, invalidate, r_busA, r_busB, r_shftamnt, r_imm, r_instruction, r_nPC, r_destination, destination_in, nPC_in, instruction_in, busA_in, busB_in, shftamnt_in, immediate_in, rs_in, rt_in, r_rt, r_rs, r_up, upper_in)
  begin  -- process nextState
    if(invalidate = '1') then
      n_instruction <= o_nop;
      n_nPC         <= (others => '0');
      n_busA        <= (others => '0');
      n_busB        <= (others => '0');
      n_shftamnt    <= (others => '0');
      n_imm         <= (others => '0');
      n_up          <= (others => '0');
      n_rs          <= (others => '0');
      n_rt          <= (others => '0');
      n_destination <= (others => '0');
      
    else
      if(holdStage = '1') then
        n_instruction <= r_instruction;
        n_nPC         <= r_nPC;
        n_busA        <= r_busA;
        n_busB        <= r_busB;
        n_shftamnt    <= r_shftamnt;
        n_imm         <= r_imm;
        n_up          <= r_up;
        n_rs          <= r_rs;
        n_rt          <= r_rt;
        n_destination <= r_destination;
      else
        n_nPC         <= nPC_in;
        n_instruction <= instruction_in;
        n_busA        <= busA_in;
        n_busB        <= busB_in;
        n_shftamnt    <= shftamnt_in;
        n_imm         <= immediate_in;
        n_up          <= upper_in;
        n_rs          <= rs_in;
        n_rt          <= rt_in;
        n_destination <= destination_in;
      end if;
    end if;
    
    
  end process nextState;

  

end idInterstageReg_arch;
